package com.ettractions.kiosk.mediators
{
	import com.ettractions.kiosk.components.ContentView;
	import com.ettractions.kiosk.events.BrochureSelectedEvent;
	import com.ettractions.kiosk.events.SelectBrochureEvent;
	import com.ettractions.kiosk.models.KioskModel;
	import com.ettractions.kiosk.utils.ViewUtils;
	import com.greensock.TweenLite;
	
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import mx.collections.ArrayList;
	
	import org.robotlegs.mvcs.Mediator;
	
	import spark.components.supportClasses.ItemRenderer;
	
	public class ContentViewMediator extends Mediator
	{
		private static const LIST_ITEM_COUNT:uint = 23;
		
		private static const DISPLAYED_LIST_ITEM_COUNT:uint = 7;
		
		private static const LIST_IDLE_X:int = -1311;
		
		private static const TWEEN_DURATION:Number = 0.5;
		
		[Inject]
		public var model:KioskModel;
		
		[Inject]
		public var view:ContentView;
		
		private var _tween:TweenLite;
		
		private var _dragStartPoint:Point;
		
		private var _mouseDownOnCenterItem:Boolean;
		
		private var _currentBrochureIndex:int = -1;
		
		private var _dragging:Boolean = false;
		
		private var _preDragMiddleItemIndex:int;
		
		private var _currentMiddleItemIndex:int;
		
		override public function onRegister():void
		{
			view.visible = false;
			
			eventDispatcher.addEventListener(BrochureSelectedEvent.BROCHURE_SELECTED, handleBrochureSelected);
			
			view.dragArea.addEventListener(MouseEvent.MOUSE_DOWN, handleDragAreaMouseDown);
			
			view.previousButton.addEventListener(MouseEvent.CLICK, handleButtonClick);
			view.nextButton.addEventListener(MouseEvent.CLICK, handleButtonClick);			
		}
		
		private function synchronizeLists():void
		{
			var middleItemIndex:int = getItemUnderGlobalPointIndex(view.dragArea.localToGlobal(new Point(view.dragArea.width / 2, view.dragArea.y)));
			
			if (_currentMiddleItemIndex != middleItemIndex)
			{
				view.brochure.visible = false;
				
				dispatchBrochureOffsetEvent(middleItemIndex - _currentMiddleItemIndex);
				
				_currentMiddleItemIndex = middleItemIndex;
				
				view.coverflowList.selectedIndex = view.coverflow.selectedIndex = middleItemIndex;
			}
		}
		
		private function updateLists():void
		{
			// HACK!
			view.coverflow.skipTransitionOnce = true;
			
			// Update the data in both lists
			view.ribbonList.dataProvider = view.coverflowList.dataProvider = ViewUtils.generateListDataProvider(model.expandedBrochures, LIST_ITEM_COUNT, -1, _currentBrochureIndex);
			
			// Re-center the selectedIndex properties for both lists
			view.ribbonList.selectedIndex = view.coverflowList.selectedIndex = view.coverflow.selectedIndex = Math.floor(LIST_ITEM_COUNT / 2);
			
			// Re-center the ribbon x value
			view.ribbonList.x = LIST_IDLE_X;
			
			// Display the brochure
			view.brochure.visible = true;
		}
		
		private function tweenToItem(index:int):void
		{
			_tween = new TweenLite(
				view.ribbonList,
				TWEEN_DURATION,
				{
					x:LIST_IDLE_X + view.ribbonList.dataGroup.getElementAt(0).width * (Math.floor(LIST_ITEM_COUNT / 2) - index),
					onUpdate:handleTweenUpdate,
					onComplete:handleTweenComplete
				}
			);
		}
		
		private function dispatchBrochureOffsetEvent(offset:int):void
		{
			eventDispatcher.dispatchEvent(new SelectBrochureEvent(SelectBrochureEvent.SELECT_BROCHURE, null, offset));
		}
		
		private function getItemUnderGlobalPointIndex(point:Point):int
		{
			for (var i:uint=0; i<LIST_ITEM_COUNT; i++)
				if (ItemRenderer(view.ribbonList.dataGroup.getElementAt(i)).hitTestPoint(point.x, point.y))
					return i;
			
			return -1;
		}
				
		private function handleBrochureSelected(event:BrochureSelectedEvent):void
		{
			var previousBrochureIndex:int = _currentBrochureIndex;
			
			_currentBrochureIndex = event.index;
			
			if (event.brochure == null)
				view.visible = false;
			
			else if (!view.visible)
			{
				updateLists();
				
				view.visible = true;
			}
			
			else if (!_tween
			&& !_dragging
			&& previousBrochureIndex != _currentBrochureIndex)
			{
				if (Math.abs(_currentBrochureIndex - previousBrochureIndex) <= DISPLAYED_LIST_ITEM_COUNT)
					tweenToItem(Math.floor(LIST_ITEM_COUNT / 2) + _currentBrochureIndex - previousBrochureIndex);
				
				else
					updateLists();
			}
		}
		
		private function handleDragAreaMouseDown(event:MouseEvent):void
		{
			if (!_tween)
			{
				_dragStartPoint = view.dragArea.localToGlobal(new Point(view.dragArea.mouseX, view.dragArea.mouseY));
				
				_mouseDownOnCenterItem = ItemRenderer(view.ribbonList.dataGroup.getElementAt(Math.floor(LIST_ITEM_COUNT / 2))).hitTestPoint(_dragStartPoint.x, _dragStartPoint.y);
				
				view.ribbonList.startDrag(false, new Rectangle(-3000, 0, 3000, 0));
				
				view.addEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
				
				view.stage.addEventListener(MouseEvent.MOUSE_UP, handleStageMouseUp);
				
				_currentMiddleItemIndex = getItemUnderGlobalPointIndex(view.dragArea.localToGlobal(new Point(view.dragArea.width / 2, view.dragArea.y)));
				
				_dragging = true;				
			}
		}
		
		private function handleMouseMove(event:MouseEvent):void
		{
			synchronizeLists();
		}		
		
		private function handleStageMouseUp(event:MouseEvent):void
		{
			var middleItemIndex:int = Math.floor(LIST_ITEM_COUNT / 2);
			
			view.removeEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
			
			view.stage.removeEventListener(MouseEvent.MOUSE_UP, handleStageMouseUp);
			
			view.ribbonList.stopDrag();
			
			_dragging = false;
			
			// Click
			if (_dragStartPoint.equals(view.dragArea.localToGlobal(new Point(view.dragArea.mouseX, view.dragArea.mouseY))))
			{
				if (!_mouseDownOnCenterItem)
					tweenToItem(getItemUnderGlobalPointIndex(_dragStartPoint));
			}
			
			// Drag
			else
				tweenToItem(_currentMiddleItemIndex);
		}
		
		private function handleButtonClick(event:MouseEvent):void
		{
			switch (event.target)
			{
				case view.previousButton:
					dispatchBrochureOffsetEvent(-1);
					break;
				
				case view.nextButton:
					dispatchBrochureOffsetEvent(1);
					break;				
			}
		}
		
		private function handleTweenUpdate():void
		{
			synchronizeLists();	
		}
		
		private function handleTweenComplete():void
		{
			updateLists();
			
			_tween = null;
		}
	}
}